<?php
if (!defined('BASEPATH'))
	exit ('No direct script access allowed');

class Auth {
	private $user;
	private $user_data;
	private $CI;

	/**
	 * This gets called at each page opening
	 */
	function Auth() {
		$this->CI = & get_instance();
		//user id is loaded from session data 
		$this->user = $this->CI->session->userdata('user_id');
		//user model is loaded, since it will be needed at some point
		$this->CI->load->model('User_model');
		//in case user isn't logged, we try autologging him in
		if (!$this->user)
			$this->autologin();
		//forces to reload, cause user loggation isn't checked otherwise
		$this->CI->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");
	}

	/**
	 * Automatically logs a user in if he has the necessary informations in his cookies
	 * Returns the user id (null if user is unlogged)
	 */
	function autologin() {
		if (!$this->user) {
			$ck_login = get_cookie('cr_auth_login', TRUE);
			if ($ck_login != false) {
				$ck_pwd = get_cookie('cr_auth_pwd', TRUE);
				$this->login($ck_login, $ck_pwd, true);
			}
		}
		return $this->user;
	}

	/**
	 * Sets whether a user should autolog or not
	 * Returns whether the autologin option is activated or not
	 */
	function set_autologin($state) {
		if ($this->is_logged()) {
			if ($state) {
				set_cookie($this->make_cookie('login', $this->user_data['nickname']));
				set_cookie($this->make_cookie('pwd', $this->user_data['pwdhash']));
			} else {
				delete_cookie('cr_auth_login');
				delete_cookie('cr_auth_pwd');
			}
		}
		return FALSE;
	}

	/**
	 * Returns whether the user is logged in or not
	 */
	function is_logged() {
		return ($this->user);
	}

	/**
	 * Logs the user with the given login and password in
	 * Returns the logged user info (or null if login/password was wrong)
	 */
	function login($login, $passwd, $pwd_ishashed = false) {
		if ($this->CI->User_model->load_user_from_nick($login)) {
			$this->user_data = $this->CI->User_model->data;
			$this->user = $this->user_data['user_id'];
			if (($pwd_ishashed && $passwd == $this->user_data['pwdhash']) 
			|| (!$pwd_ishashed && $this->CI->User_model->password_match($passwd))) {
				//update last login date
				$this->CI->User_model->save_user($this->user, 
					array('last_connection' => date('Y-m-d H:i:s')));
				$this->CI->session->set_userdata(array (
					'user_id' => $this->user));
				if (!$this->CI->input->cookie('ci_session')) {
					$this->user = $this->user_data = null;
					echo 'cookies needed !<br />';
				}
			}
			else {
				$this->user = $this->user_data = null;
			}
			return $this->user_data;
		}
		return null;
	}

	/**
	 * Logs the user out
	 */
	function logout() {
		if ($this->is_logged()) {
			$this->CI->session->unset_userdata('user_id');
			$this->set_autologin(false);
			$this->user = null;
			$this->user_data = null;
		}
	}

	/**
	 * Returns the user info
	 */
	function get_infos() {
		if (!$this->user_data)
			$this->refresh_info();
		return $this->user_data;
	}

	/**
	 * Reloads the user's info from the database
	 */
	function refresh_info() {
		if ($this->user) {
			$this->CI->User_model->load_user_from_id($this->user);
			$this->user_data = $this->CI->User_model->data;
		}
	}
	
	/**
	 * Returns the logged user's id
	 */
	function get_user_id() {
		return $this->user;
	}

	/**
	 * Makes a cookie for this lib
	 */
	private static function make_cookie($name, $value) {
		return array (
			'name' => 'cr_auth_'.$name,
			'value' => $value,
			'expire' => '604800'
		);
	}

	/**
	 * Returns whether the currently logged user can do the $action action on the data $datatype.
	 * An optional $id may be supplied for single-access actions :
	 * 		if $datatype = 'user', the user id is awaited (requested user is logged user)
	 * 		if $datatype = 'pkg', the package id is awaited (package belongs to logged user)
	 * 		if $datatype = 'bch', the branch id is awaited (branch belongs to logged user)
	 * 		if $datatype = 'rls', the release id is awaited (release belongs to logged user)
	 * 		if $datatype = 'privdata', the user id is awaited (requested user is logged user)
	 * Though, if the action is 'add', then the id of the container element is awaited.
	 *   ie, if you want to add a branch, provide the package id.
	 *   if you want to add a release, provide the branch id
	 */
	function has_rights_to($action, $datatype, $id = null) {
		$this->get_infos();
		if (isset($this->user_data['rights']))
			$usrrights = $this->user_data['rights'];
		else
			$usrrights = 0;
		/*
		 * 0 : unlogged user
		 * 1 : logged user
		 * 2 : moderator
		 * 3 : super-moderator
		 * 4 : admin
		 * the tens digit indicates what level is required to do the action without any further identification
		 * the units digit indicates what level is required to do the action with an id check
		 */
		static $allowance = array(
			'edit' => array(
				'article' => 31,
				'user' => 31,
				'pkg' => 31,
				'bch' => 31,
				'rls' => 31,
				'admin' => 44,
				'privdata' => 31
				),
			'delete' => array(
				'article' => 31,
				'user' => 31,
				'pkg' => 31,
				'bch' => 31,
				'rls' => 31,
				'admin' => 44,
				'privdata' => 31
				),
			'lookat' => array(
				'article' => 00,
				'user' => 00,
				'pkg' => 00,
				'bch' => 00,
				'rls' => 00,
				'admin' => 44,
				'privdata' => 31
				),
			'list' => array(
				'article' => 00,
				'user' => 11,
				'pkg' => 00,
				'bch' => 00,
				'rls' => 00,
				'privdata' => 33
				),
			'add' => array(
				'article' => 31,
				'user' => 00,
				'mod' => 33,
				'smod' => 44,
				'admin' => 44,
				'pkg' => 11,
				'bch' => 31,
				'rls' => 31
				),
			'mod' => array(
				'article' => 33,
				'user' => 33,
				'pkg' => 22,
				'bch' => 22,
				'rls' => 22,
				'admin' => 44,
				'privdata' => 33
				)
			);
		if ('user' == $datatype && 'edit' == $action && $id != $this->user) {
			$this->CI->User_model->load_user_from_id($id);
			$editedusrrights = $this->CI->User_model->data['rights'];
			return $usrrights > 2 && $editedusrrights < $usrrights;
		}
		if ($usrrights * 11 >= $allowance[$action][$datatype])
			return true;
		if ($id && $usrrights >= $allowance[$action][$datatype] % 10) {
			//check id
			if ('user' == $datatype)
				return $id == $this->user;
			else if ('rls' == $datatype && 'add' == $action) {
			   	if (!isset($this->CI->AuthBch))
			   		$this->CI->load->model('Branch_model','AuthBch');
			   	return ($this->CI->AuthBch->is_responsible($this->user, $id));
			}
			else if ('rls' == $datatype) {
			   	if (!isset($this->CI->AuthRls))
			   		$this->CI->load->model('Release_model','AuthRls');
			   	return ($this->CI->AuthRls->is_responsible($this->user, $id));
			}
			else if ('bch' == $datatype && 'add' == $action) {
			   	if (!isset($this->CI->AuthPkg))
			   		$this->CI->load->model('Package_model','AuthPkg');
			   	return ($this->CI->AuthPkg->is_responsible($this->user, $id));
			}
			else if ('bch' == $datatype) {
			   	if (!isset($this->CI->AuthBch))
			   		$this->CI->load->model('Branch_model','AuthBch');
			   	return ($this->CI->AuthBch->is_responsible($this->user, $id));
			}
			else if ('pkg' == $datatype) {
			   	if (!isset($this->CI->AuthPkg))
			   		$this->CI->load->model('Package_model','AuthPkg');
			   	return ($this->CI->AuthPkg->is_responsible($this->user, $id));
			}
			else if ('privdata' == $datatype)
			   	return ($id == $this->user);
			else if ('article' == $datatype) {
			   	if (!isset($this->CI->AuthArticle))
			   		$this->CI->load->model('Article_model','AuthArticle');
			   	return ($this->CI->AuthArticle->is_responsible($this->user, $id));
			}
		}
		
		return false;
	}

}

?>
